<template>
    <div>
      <!-- 仅图片：picture-card + 加号 -->
      <el-upload
        v-if="modeImage"
        v-model:file-list="uiFileList"
        class="avatar-uploader"
        :action="action"
        :headers="headers"
        :on-success="onSuccess"
        :before-upload="beforeUpload"
        :on-remove="onRemove"
        :before-remove="beforeRemove"
        :limit="limit"
        name="fileList"
        list-type="picture-card"
        :accept="finalAccept"
      >
        <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
        <template #tip>
          <div class="el-upload__tip">支持上传 {{ acceptText }} 格式图片，大小不超过 2MB</div>
        </template>
      </el-upload>
  
      <!-- auto / file：图片缩略图+普通文件列表。用 v-model:file-list，不再重复传 :file-list -->
      <el-upload
        v-else
        v-model:file-list="uiFileList"
        class="upload-demo"
        :action="action"
        :headers="headers"
        name="fileList"
        :on-success="onSuccess"
        :before-upload="beforeUpload"
        :on-remove="onRemove"
        :before-remove="beforeRemove"
        :limit="limit"
        :accept="finalAccept"
        list-type="picture"
      >
        <el-button type="primary">点击上传</el-button>
        <template #tip>
          <div class="el-upload__tip">
            <template v-if="modeAuto">
              支持上传图片（{{ imageText }}，≤2MB）和其他文件（≤10MB）
            </template>
            <template v-else>
              支持上传 {{ acceptText }} 格式文件，单个文件不超过 10MB
            </template>
          </div>
        </template>
      </el-upload>
    </div>
  </template>
  
  <script setup>
  import { ref, computed, watch, nextTick } from 'vue';
  import { getToken } from '@/utils/auth';
  import { ElMessage, ElMessageBox } from 'element-plus';
  import { Plus } from '@element-plus/icons-vue';
  import { defineExpose } from 'vue';
  
  const uiFileList   = ref([]);        // UI 用（必须包含 url/name/fileId/uid）
  const serverItems  = ref([]);        // 新上传返回的原始条目（含 fileId/filePath）
  const uploadedIds  = ref([]);        // 新上传得到的 fileId（仅新增）
  const baseIds      = ref([]);        // 初始传入的 ids（来自 props）
  const uidToId      = ref(new Map()); // uid -> fileId（删除/重算时使用）
  
  const clearFileList = () => {
    uiFileList.value = [];
    serverItems.value = [];
    uploadedIds.value = [];
    uidToId.value = new Map();
  };
  defineExpose({ clearFileList });
  
  const action  = ref(import.meta.env.VITE_APP_UPLOAD_URL + '/file_manage/upload');
  const headers = ref({ Authorization: 'Bearer ' + getToken() });
  
  const props = defineProps({
    // 父可用 v-model:fileIds 或 v-model:file-ids 绑定；此处 prop 统一是 camelCase: fileIds
    fileIds:  { type: [Array, String], default: () => [] }, // 支持数组或逗号串
    imageUrl: { type: String, default: '' },
    limit:    { type: Number, default: 5 },
    fileList: { type: Array,  default: () => [] },          // 回显列表
    type:     { type: String, default: 'auto', validator: v => ['image','file','auto'].includes(v) },
    accept:   { type: String, default: '' }
  });
  
  const emit = defineEmits(['update:fileIds', 'update:file-ids', 'success', 'update:imageUrl']);
  
  const modeImage = computed(() => props.type === 'image');
  const modeFile  = computed(() => props.type === 'file');
  const modeAuto  = computed(() => props.type === 'auto');
  
  const imageText = computed(() => 'JPG/PNG/GIF');
  const acceptText = computed(() => {
    if (props.accept) {
      if (props.accept === 'image/*') return imageText.value;
      if (props.accept === '*') return '所有';
      return props.accept.split(',').map(t => t.replace('.', '').toUpperCase()).join('/');
    }
    if (modeImage.value) return imageText.value;
    if (modeFile.value)  return '所有';
    return '图片/所有';
  });
  const finalAccept = computed(() => {
    if (props.accept) return props.accept;
    if (modeImage.value) return 'image/*';
    if (modeFile.value)  return '*';
    return '*'; // auto
  });
  
  // ===== utils =====
  const toArrayIds = (v) => {
    if (!v && v !== 0) return [];
    if (Array.isArray(v)) return v.map(String).filter(Boolean);
    if (typeof v === 'string') return v.split(',').map(s => s.trim()).filter(Boolean);
    return [];
  };
  const uniq = (arr) => Array.from(new Set(arr));
  const isArrayModel = computed(() => Array.isArray(props.fileIds));
  const emitIds = (idsArr) => {
    emit('success', idsArr);
    const out = isArrayModel.value ? idsArr : idsArr.join(',');
    // 同时兼容两种事件名：update:fileIds & update:file-ids
    emit('update:fileIds', out);
    emit('update:file-ids', out);
  };
  
  // 从文件项尽可能获取 id；必要时用 uid 映射兜底
  const pickIdFromFile = (file) => {
    const id =
      file?._fileId ||
      file?.fileId ||
      file?.response?.data?.[0]?.fileId ||
      file?.response?.fileId ||
      (file?.uid && uidToId.value.get(file.uid));
    return id ? String(id) : '';
  };
  
  // 按“当前仍存在的文件”重算 ids 并回传
  const recomputeAndEmit = (list) => {
    const ids = uniq((list || []).map(f => pickIdFromFile(f)).filter(Boolean));
    // 如果某些回显项没带 id（理论上不该发生），尝试用 baseIds 合并一次
    const merged = uniq([...ids, ...baseIds.value.filter(id => list.some(f => f.fileId === id || f._fileId === id))]);
    emitIds(merged);
  };
  
  // ===== 初始化 baseIds =====
  const initBaseIdsFromProps = () => {
    let ids = toArrayIds(props.fileIds);
    if (ids.length === 0 && Array.isArray(props.fileList)) {
      const fromList = props.fileList.map(i => i.fileId || i.id).filter(Boolean).map(String);
      ids = fromList;
    }
    baseIds.value = uniq(ids);
  };
  watch(() => props.fileIds, initBaseIdsFromProps, { immediate: true });
  
  // 回显列表 -> UI 列表，并建立 uid 映射
  watch(
    () => props.fileList,
    async (val) => {
      uiFileList.value = (val || []).map(item => {
        const url    = item.url || item.filePath;
        const name   = item.name || item.fileName || item.originalName || url || '';
        const fileId = item.fileId || item.id;
        return { ...item, url, name, fileId };
      });
  
      if (toArrayIds(props.fileIds).length === 0) {
        const fromList = (val || []).map(i => i.fileId || i.id).filter(Boolean).map(String);
        if (fromList.length) baseIds.value = uniq(fromList);
      }
  
      await nextTick();
      uiFileList.value.forEach(f => {
        const id = f.fileId;
        if (f.uid && id) uidToId.value.set(f.uid, String(id));
      });
    },
    { immediate: true }
  );
  
  // 监听 UI 列表变化，持续维护 uid -> id
  watch(
    uiFileList,
    (list) => {
      list.forEach(f => {
        const id = pickIdFromFile(f);
        if (f.uid && id) uidToId.value.set(f.uid, id);
      });
    },
    { deep: true }
  );
  
  // 单图回显
  watch(() => props.imageUrl, (value) => {
    if (!value) {
      if (modeImage.value) uiFileList.value = [];
      return;
    }
    if (modeImage.value || modeAuto.value) {
      uiFileList.value = [{
        name: value,
        url: (import.meta.env.VITE_APP_IMAFGE_URL || import.meta.env.VITE_APP_IMAGE_URL || '') + value
      }];
    }
  }, { immediate: true });
  
  // ===== 校验 =====
  const beforeUpload = (file) => {
    const isImage = file.type && file.type.startsWith('image/');
    if (modeImage.value) {
      if (!isImage) { ElMessage.error('只能上传图片文件!'); return false; }
      if (file.size / 1024 / 1024 >= 2) { ElMessage.error('图片大小不能超过 2MB!'); return false; }
      return true;
    }
    if (modeFile.value) {
      if (file.size / 1024 / 1024 >= 10) { ElMessage.error('文件大小不能超过 10MB!'); return false; }
      return true;
    }
    // auto
    if (isImage) {
      if (file.size / 1024 / 1024 >= 2) { ElMessage.error('图片大小不能超过 2MB!'); return false; }
    } else {
      if (file.size / 1024 / 1024 >= 10) { ElMessage.error('文件大小不能超过 10MB!'); return false; }
    }
    return true;
  };
  
  const beforeRemove = (uploadFile) => {
    return ElMessageBox.confirm(`确定移除 ${uploadFile.name} 吗？`).then(() => true, () => false);
  };
  
  // ===== 上传成功：建立 uid→id，随后“按当前列表”重算 ids =====
  const onSuccess = (response, uploadFile) => {
    if (response && response.code === 200) {
      const arr = Array.isArray(response.data) ? response.data : [response.data].filter(Boolean);
      serverItems.value.push(...arr);
  
      const newIds = arr.map(i => i?.fileId).filter(Boolean).map(String);
      if (newIds.length) {
        uploadedIds.value = uniq([...uploadedIds.value, ...newIds]);
        if (uploadFile?.uid && newIds.length === 1) {
          uidToId.value.set(uploadFile.uid, newIds[0]);
          uploadFile._fileId = newIds[0]; // 把 id 写回文件项，删除时也能读到
        }
      }
  
      // 同步 imageUrl（image 或 auto+图片）
      if (modeImage.value || (modeAuto.value && (uploadFile?.raw?.type || '').startsWith('image/'))) {
        const firstImg = serverItems.value.find(i => isLikelyImagePath(i?.filePath));
        if (firstImg?.filePath) emit('update:imageUrl', firstImg.filePath);
      }
  
      // 关键：基于“当前列表”重算 ids
      recomputeAndEmit(uiFileList.value);
    } else {
      ElMessage.error((response && response.msg) || '上传失败');
    }
  };
  
  // ===== 删除：不去猜“删的是谁”，直接按当前列表重算 =====
  const onRemove = (file, currentList) => {
    if (file?.uid && uidToId.value.has(file.uid)) {
      uidToId.value.delete(file.uid);
    }
    // 删除后，ElementPlus 会把“剩余列表”作为第二个参数传进来
    recomputeAndEmit(currentList || uiFileList.value);
  };
  
  // 图片判断
  function isLikelyImagePath(p) {
    if (!p || typeof p !== 'string') return false;
    const lower = p.toLowerCase();
    return ['.jpg','.jpeg','.png','.gif','.webp','.bmp'].some(ext => lower.endsWith(ext));
  }
  </script>
  
  <style scoped>
  /* 图片上传样式（保持原样） */
  :deep(.avatar-uploader) .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
  }
  :deep(.avatar-uploader) .el-upload:hover { border-color: var(--el-color-primary); }
  :deep(.avatar-uploader-icon) {
    font-size: 28px; color: #8c939d; width: 148px; height: 148px;
    text-align: center; display: flex; justify-content: center; align-items: center;
  }
  
  /* 文件列表样式 */
  :deep(.el-upload-list) { margin-top: 10px; }
  
  /* 提示文字样式 */
  .el-upload__tip {
    margin-top: 8px;
    color: var(--el-text-color-secondary);
    font-size: 12px;
    line-height: 1.5;
  }
  </style>
  